/*

Copyright (C) 2000 - 2008 Christian Kreibich <christian@whoop.org>.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies of the Software and its documentation and acknowledgment shall be
given in the documentation and software packages that this Software was
used.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/
#ifndef __nd_trace_h
#define __nd_trace_h

#include <nd.h>

#include <gtk/gtk.h>

#include <nd_dialog.h>
#include <nd_protocol_inst.h>


struct nd_trace
{
  /* There is intentionally no pointer back to the real trace --
   * by design we always pass the real trace around and can always
   * access this add-on GUI data from there.
   */

  GtkWidget     *list;                /* This trace's tcpdump list */

  /* This trace's notebook tab.

     It contains the notebook with the protocols that display a
     packet's content under the key "notebook", the clist widget
     is available via "trace_list".

     The notebook contains each protocol's tab via the
     protocol's name as key. The trace is available from the
     notebook via "trace".
  */
  GtkWidget      *tab;
  GtkWidget      *tab_label;          /* This trace's notebook tab label */

  LND_Packet     *cur_packet;         /* Current packet */
  guchar         *cur_header;

  LND_ProtoInst  *cur_pi_sel;         /* The protocol the user has selected recently. */
  LND_ProtoInst  *cur_pi;

  int             sel_handler;        /* Gtk idle handler for selecting a packet */    
};


typedef enum {
  ND_TRACE_JUMP_TOP,
  ND_TRACE_JUMP_BOTTOM,
  ND_TRACE_JUMP_NEXT,
  ND_TRACE_JUMP_PREV,
  ND_TRACE_JUMP_NEXT_SEL,
  ND_TRACE_JUMP_PREV_SEL,
  ND_TRACE_JUMP_NEXT_PROT,
  ND_TRACE_JUMP_PREV_PROT,
  ND_TRACE_JUMP_NEXT_UNFILTERED,
  ND_TRACE_JUMP_PREV_UNFILTERED,
} ND_TraceLocation;


void           nd_trace_init(void);
 
/**
 * nd_trace_new - creates a new trace.
 * @filename: canonical name of the trace file in the filesystem
 *
 * This is the constructor function for new traces. The @filename
 * is the full name of a trace file. You can pass %NULL if you don't
 * want/can provide packet data yet (as in live capture, for example).
 * If a filename is given, the file is checked for existence
 * and readability, if these checks fail, %NULL is returned. Otherwise
 * the trace is read into memory and initialized. The trace is NOT
 * automatically added to the trace registry, use nd_trace_registry_add()
 * for that purpose.
 *
 * Returns: new trace.
 */
LND_Trace     *nd_trace_new(const char *filename);

/**
 * nd_trace_close - closes a trace.
 * @trace: trace to close.
 *
 * Safe version of nd_trace_free() - if the trace was modified,
 * a dialog is opened that asks for confirmation. Only then the
 * trace is actually removed from the registry and freed.
 */
void           nd_trace_close(LND_Trace *trace);

/**
 * nd_trace_free - cleans up trace.
 * @trace: trace to free.
 *
 * This function closes the tcpdump connection for this trace
 * and releases the memory it occupies, together with all its
 * packets.
 */
void           nd_trace_free(LND_Trace *trace);


ND_Trace      *nd_trace_get(const LND_Trace *trace);

/**
 * nd_trace_add_proto_tab - adds a protocol tab to a trace
 * @trace: trace to add tab to.
 * @proto: protocol for which to add a trace.
 * @nesting: nesting level of protocol.
 *
 * The function creates the necessary widgets to build a new tab
 * that gets added to the trace's protocols notebook. If there already
 * is a tab for the given protocol/nesting combo, the function does
 * nothing and returns.
 */
void           nd_trace_add_proto_tab(LND_Trace *trace,
				      LND_Protocol *proto,
				      guint nesting);

/**
 * nd_trace_set_current_proto_selection - sets the preferred protocol of this trace.
 * @trace: trace to set selection in.
 * @pi: new protocol instance.
 *
 * When browsing through packets in a trace, there is the problem of
 * choosing a protocol to be selected initially (just like you want
 * your cursor to stay in the same column as much as possible in 
 * a text editor). Use this function to set that protocol. The protocol
 * instance data is copied internally, so you don't need to allocate
 * @pi.
 */
void           nd_trace_set_current_proto_selection(LND_Trace *trace,
						    const LND_ProtoInst *pi);


/**
 * nd_trace_set_current_proto - sets current protocol of a trace.
 * @trace: trace to set selection in.
 * @pi: new protocol instance selection.
 * @gui_update: whether to update the GUI.
 *
 * This function sets the current protocol in a trace, updating
 * the GUI. It does not influenced the preferred protocol selction
 * which is set using nd_trace_current_protocol_selection().
 * Sometimes it makes sense to not update the GUI immediately,
 * e.g. when you know that another call to this function will follow
 * soon. In this case, set @gui_update to %FALSE. The protocol
 * instance data is copied internally, so you don't need to allocate
 * @pi.
 */
void           nd_trace_set_current_proto(LND_Trace *trace,
					  const LND_ProtoInst *pi,
					  gboolean gui_update);

/**
 * nd_trace_get_proto_info - returns protocol info structure
 * @trace: trace to query.
 * @proto: protocol type to look up.
 * @nesting: which protocol instance to look up.
 *
 * In a trace's protocol notebook, each tab has an associated
 * #ND_ProtoInfo structure. This function is used to look up these
 * structures.
 *
 * Returns: protocol info if found, %NULL otherwise.
 */
LND_ProtoInfo *nd_trace_get_proto_info(const LND_Trace *trace,
				       const LND_Protocol *proto,
				       guint nesting);


/**
 * nd_trace_get_current_proto_inst - returns currently selected protocol instance.
 * @trace: trace to return current protocol from.
 *
 * This function returns the currently selected protocol of
 * the given trace.
 *
 * Returns: current protocol instance or %NULL if n/a.
 */
LND_ProtoInst  *nd_trace_get_current_proto_inst(const LND_Trace *trace);


/**
 * nd_trace_get_current_proto_header - returns header of the current protocol in current packet.
 * @trace: trace to return header from.
 *
 * This is a convenience function that returns a pointer to the
 * header of the currently selected protocol in the current packet
 * of the given trace. You can then cast this pointer to the
 * appropriate structure. If this function is not applicable,
 * %NULL is returned.
 *
 * Returns: pointer to current protocol in current packet.
 */
guchar        *nd_trace_get_current_proto_header(const LND_Trace *trace);


/**
 * nd_trace_get_current_packet - returns currently selected packet.
 * @trace: trace to look up packet in.
 *
 * Each trace has a currently selected packet, which may be %NULL.
 * This function returns it.
 *
 * Returns: current packet or NULL if n/a.
 */
LND_Packet    *nd_trace_get_current_packet(const LND_Trace *trace);


/**
 * nd_trace_set_current_packet - sets currently selected packet in trace.
 * @trace: trace to set packet in.
 * @packet: packet to set as current one.
 *
 * This function sets the given packet as the current one in
 * the trace. Normally this could be done with the packet alone
 * (using packet->trace), but this function also allows you to
 * pass %NULL as @packet to unset the current packet. In both
 * cases the GUI is updated accordingly.
 */
void           nd_trace_set_current_packet(LND_Trace *trace,
					   LND_Packet *packet);

/**
 * nd_trace_load_dialog - opens dialog for loading a trace.
 */
void           nd_trace_load_dialog(void);

/**
 * nd_trace_save_as_dialog - opens a dialog for saving a trace.
 * @trace: trace to save.
 * @callback_finished: callback to call after file is saved.
 * @user_data: arbitrary data to pass to @callback_finished.
 *
 * The function opens a dialog to save @trace, if the trace got
 * saved after the user closes the dialog, the callback is
 * called with the given @user_data. This function gets called
 * by nd_trace_save() when the trace doesn't yet have a name.
 */
void           nd_trace_save_as_dialog(LND_Trace *trace,
				       ND_DialogCallback callback_finished,
				       void *user_data);

/* nd_trace_save - saves given trace, using dialog if necessary.
 * @trace: trace to save.
 *
 * The trace is saved to disk. If it doesn't have a name yet,
 * nd_trace_save_as_dialog is called. If saving was successful,
 * %TRUE is returned, %FALSE otherwise.
 *
 * Returns: success status.
 */
gboolean       nd_trace_save(LND_Trace *trace);


/* nd_trace_save_as - saves trace under new name and updates GUI accordingly.
 * @trace: trace to save.
 *
 * The name of the trace is changed and the trace saved subsequentially.
 * If saving was successful, %TRUE is returned, %FALSE otherwise.
 *
 * Returns: success status.
 */
gboolean       nd_trace_save_as(LND_Trace *trace, const char *filename);

/**
 * nd_trace_get_notebook - returns protocol notebook.
 * @trace: trace to query.
 *
 * This function provides access to the GTK notebook that contains
 * the protocols for this trace.
 *
 * Returns: the protocols notebook.
 */
GtkNotebook   *nd_trace_get_notebook(const LND_Trace *trace);

/**
 * nd_trace_goto - selects a different packet in the trace.
 * @trace: trace to jump around in.
 * @loc: location to jump to.
 *
 * The function selects a new packet in the trace or just scrolls to
 * a different part in the trace, depending on the location specified in @loc.
 */
void           nd_trace_goto(LND_Trace *trace, ND_TraceLocation loc);

#endif
